package org.fizz.ass;

import java.util.Stack;

import org.fizz.ass.html.AssHTMLDocument;
import org.fizz.ass.html.ConstantEnum;
import org.fizz.ass.html.Element;
import org.fizz.ass.html.EmptyElement;


/**
 * ass解析HTML的回调类
 * @author FIZZ
 * @version ass-1.0, 2014-4-20
 * @since 1.o
 */
public class AssParserCallback implements IAssParserCallback , AssConstants{

	private Stack<Element> elementStack;
	
	private AssHTMLDocument assHTMLdoc;
	
	public AssParserCallback(){
		elementStack = new Stack<Element>();
		
		assHTMLdoc = new AssHTMLDocument();
		
	}
	
	public AssHTMLDocument getAssHTMLDocument(){
		return assHTMLdoc;
	}
	
	@Override
	public void handlerDoctype(String tagContent) {
		// TODO Auto-generated method stub
		//System.out.println("handlerDoctype: " + tagContent);
		
		String doctype = getDoctype(tagContent);
		assHTMLdoc.setDoctype(doctype);
		
	}
	
	@Override
	public void handlerTagStart(String tagContent) {
		// TODO Auto-generated method stub
		//System.out.println("handlerTagStart: " + tagContent);
		
		Element element = tagStart2Element(tagContent);
		
		if(!elementStack.isEmpty()){
			Element peekElement = elementStack.peek();
			assHTMLdoc.addElement(element, peekElement);
		}else{
			assHTMLdoc.addElement(element, null);
		}
		
		if(!EmptyElement.contain(element.getName())){//不是空元素
			elementStack.push(element);
		}
		
		
		
		
	}

	@Override
	public void handlerTagEnd(String tagContent) {
		// TODO Auto-generated method stub
		//System.out.println("handlerTagEnd: " + tagContent);
		
		String tagName = getTagNameForEnd(tagContent);
		Element peekElement = elementStack.peek();
		if(peekElement != null){
			if(peekElement.getName().equalsIgnoreCase(tagName)){
				elementStack.pop();//如果栈顶元素名相同，则该元素从栈顶弹出
			}
		}
		
	}

	@Override
	public void handlerReadEnding() {
		System.out.println("read Ending");
		
	}

	@Override
	public void handlerText(String text) {
		// TODO Auto-generated method stub
		//System.out.println("handlerText ： " + text);
		
		Element peekElement = elementStack.peek();
		if(peekElement != null){
			peekElement.setText(text);
		}
	}

	@Override
	public void handlerSimpleTag(String tagContent) {
		// TODO Auto-generated method stub
		//System.out.println("handlerSimpleTag ： " + tagContent);
		
		Element simpleEle = simpleTag2Element(tagContent);
		if(!elementStack.isEmpty()){
			Element peekElement = elementStack.peek();
			assHTMLdoc.addElement(simpleEle, peekElement);
		}else{
			assHTMLdoc.addElement(simpleEle, null);
		}
	}

	@Override
	public void handlerComment(String tagContent) {
		// TODO Auto-generated method stub
		//System.out.println("handlerComment ： " + tagContent);
		/* 注释消息不做添加 */
	}
	
	/**
	 * 去掉前后的间括号'&lt;'...'&gt;'
	 * @param str
	 * @since 1.0
	 */
	private String removeLTGT(String str){
		return str.trim().substring(1, str.length()-1);
	}
	
	/**
	 * 返回DOCTYPE
	 * @param str
	 * @return DOCTYPE
	 * @since 1.0
	 */
	private String getDoctype(String tagContent){
		tagContent = removeLTGT(tagContent);
		return tagContent.replace(ConstantEnum.DOCTYPE.getName(), "").trim();//replace掉!DOCTYPE
	}
	
	/**
	 * 标签开始时，将标签内的内容转换成HTML元素
	 * @param tagContent 标签内的内容
	 * @return HTML元素
	 * @since 1.0
	 */
	private Element tagStart2Element(String tagContent){
		tagContent = removeLTGT(tagContent);//去掉前后的间括号
		return str2Element(tagContent);
	}
	
	/**
	 * 标签结束时，返回结束标签的名字
	 * @param tagContent 标签内的内容
	 * @return 结束标签的名字
	 * @since 1.0
	 */
	private String getTagNameForEnd(String tagContent){
		tagContent = removeLTGT(tagContent);//去掉前后的间括号
		return tagContent.trim().substring(1).trim();//去掉开始的斜线 /
	}
	
	
	/**
	 * 将简单标签内的内容转换成HTML元素
	 * @param tagContent 标签内的内容
	 * @return HTML元素
	 * @since 1.0
	 */
	private Element simpleTag2Element(String tagContent){
		tagContent = removeLTGT(tagContent);//去掉前后的间括号
		tagContent = tagContent.substring(0, tagContent.length()-1);//去掉最后的斜线 /
		
		return str2Element(tagContent);
	}
	
	/**
	 * 将没有前后间括号和斜线(简单标签)的纯标签内的内容 转换成HTML元素并返回
	 * @param tagContent 没有前后间括号和斜线(简单标签)的纯标签内的内容
	 * @return HTML元素
	 * @since 1.0
	 */
	private Element str2Element(String tagContent){
		//<meta name ="stencil" content="PGLS000022" />,,,name后有空，如果用split(BLANK)会有问题
		
		String tagName = "";
		Element element;
		
		int firstBlankIndex = tagContent.trim().indexOf(SPACE);//第一个空白出现的位置
		if(firstBlankIndex != -1){// 如果 ==-1说明没有属性值，只有一个标签名
			tagName = tagContent.substring(0, firstBlankIndex).trim();//元素是标签名
			element = new Element(tagName);
			
			//剩余的字符串，就是属性的key-value对
			String remainTagContent = tagContent.substring(firstBlankIndex).trim();
			int equalIndex = -1;//等好的索引位置
			while((equalIndex = remainTagContent.indexOf(EQUAL_STR)) != -1){
				String key = remainTagContent.substring(0, equalIndex).trim();//得到属性的key 
				remainTagContent = remainTagContent.substring(equalIndex+1).trim();//去掉等号
				int nextBlankIndex = remainTagContent.indexOf(SPACE);//下一个空白出现的位置
				String value = "";
				if(nextBlankIndex == -1){//==-1 说明后面就只剩属性值了
					value = remainTagContent.substring(0).trim();//带有引号的属性值
					remainTagContent = "";
				}else{
					value = remainTagContent.substring(0, nextBlankIndex).trim();//带有引号的属性值
					//获得下一个空白出现的位置后面的字符串
					remainTagContent = remainTagContent.substring(nextBlankIndex).trim();
				}
				if(value.length() > 2){
					value = value.substring(1, value.length()-1);//去掉引号
				}
				element.addAttribute(key, value);
			}
		}else{
			tagName = tagContent.trim();
			element = new Element(tagName);
		}
		
		
		
		return element;
	}

}
